/** ****************************************************************************
 * @file 	modbusport.cpp
 * @author 	mojinpan
 * @copyright copyright (c) 2018-2020 mojinpan. All rights reserved.
 * @brief 	modbus通讯接口抽象基类
 *
 * @version 	V1.0
 * @date 	2025-06-17
 * @details
 * 1.初稿
 *******************************************************************************/
#include "modbusport.hpp"

// 新增：注册Modbus实例与地址的映射
void SerialPort::registerContext(uint8_t addr, void *cxt)
{
    std::lock_guard<std::mutex> lock(m_mutex); // 加锁保护共享数据
    m_addrToCxt[addr] = cxt;                   // 地址 -> 实例指针
    m_cxtToBuf[cxt] = {};                      // 初始化实例专属缓冲区（空）
}

// 新增：注销Modbus实例与地址的映射
void SerialPort::unregisterContext(uint8_t addr)
{
    std::lock_guard<std::mutex> lock(m_mutex);
    auto it = m_addrToCxt.find(addr);
    if (it != m_addrToCxt.end())
    {
        void *cxt = it->second;
        m_cxtToBuf.erase(cxt); // 删除实例专属缓冲区
        m_addrToCxt.erase(it); // 删除地址映射
    }
}
// 串口接收回调（来自comm_adapter::Comm::Parent）
void SerialPort::onRecv(const std::string &from_who, const void *data_ptr, size_t data_size)
{
    if (!data_ptr || data_size == 0) return;

    std::lock_guard<std::mutex> lock(m_mutex); // 加锁保护
    const uint8_t *data = static_cast<const uint8_t *>(data_ptr);

    if (data_size >= 1)
    {
        uint8_t target_addr = data[0];
        auto it = m_addrToCxt.find(target_addr);
        if (it != m_addrToCxt.end())
        {
            void *target_cxt = it->second;
            m_cxtToBuf[target_cxt].insert(m_cxtToBuf[target_cxt].end(), data, data + data_size);
            m_recvCond.notify_all(); // 数据入队后通知等待线程
        }
    }
}
// ModbusPort接收接口实现
int SerialPort::recv(void *cxt, uint8_t *buf, size_t len)
{
    if (!buf || len == 0 || !cxt) return 0;

    std::unique_lock<std::mutex> lock(m_mutex);
    // 阻塞等待直到找到实例且缓冲区有数据
    m_recvCond.wait(lock, [this, cxt]() 
    {
        auto it = m_cxtToBuf.find(cxt);
        return it != m_cxtToBuf.end() && !it->second.empty();
    });

    // 读取数据并更新缓冲区
    auto it = m_cxtToBuf.find(cxt);
    std::vector<uint8_t> &instance_buf = it->second;
    size_t read_size = std::min(len, instance_buf.size());
    std::copy(instance_buf.begin(), instance_buf.begin() + read_size, buf);
    instance_buf.erase(instance_buf.begin(), instance_buf.begin() + read_size);
    return static_cast<int>(read_size);
}

// ModbusPort发送接口实现
int SerialPort::send(void *cxt, const uint8_t *buf, size_t len)
{
    if (!buf || len == 0 || !m_isConnected || !m_comm) return -1;
    m_comm->send(buf, len); // 具体接口需根据comm.hpp实际定义调整
    return static_cast<int>(len);
}
